//
// Author: Vladimir Migashko <migashko@gmail.com>, (C) 2011
//
// Copyright: See COPYING file that comes with this distribution
//

#ifndef HITLIST_HITLIST_MEHTOD_HPP
#define HITLIST_HITLIST_MEHTOD_HPP

#include <fas/adv/json_rpc3/method.hpp>
#include "hitlist_request_json.hpp"
#include "hit_item_json.hpp"
#include "ihitlist.hpp"
#include "tags.hpp"


namespace aa = ::fas::aop;
namespace ap = ::fas::pattern;
namespace ad = ::fas::adv;
namespace ajr = ::fas::adv::json_rpc3;

/** @brief Метод hitlist json-rpc аспекта соединия
 *
 * Добавляется в аспект соединения с групповым тегом _gmethod_,
 * чтобы мог быть вызван аспектом json-rpc по имени, возращаемом 
 * методом name()
 */
struct hitlist_method
{
  ihitlist* hitlist;

  hitlist_method(): hitlist(0) {}

  /// имя метода json-rpc
  const char *name() const { return "hitlist"; }

  /// тип входящего запроса на вызов метода (json)
  typedef hitlist_request_json invoke_request;
  /// тип ответа на входящий запрос (json)
  typedef aj::array<hit_item_json> invoke_response;

  /// тип входящего уведомления (json)
  typedef hitlist_request_json invoke_notify;
  /// тип исходящего уведомления (json)
  typedef aj::array<hit_item_json> call_notify;

  /// Обработка входящего запроса
  /** @param t - контекст вызова (ссылка на объект соединения )
    * @param req - запрос 
    * @param id - идентификатор вызова метода
    * @param res - ответ
    * @return true - если ответ готов (всегда);
    */
  template<typename T>
  bool request(T& t, const hitlist_request& req, int id, std::vector<hit_item>& res )
  {
    if (req.type == hitlist_request::hits_m)
      hitlist->month_hitlist(req.first_id, req.offset, req.limit, res );
    else if (req.type == hitlist_request::hits_d)
      hitlist->day_hitlist(req.first_id, req.offset, req.limit, res );
    /// сообщаем что ответ готов
    return true;
  }

  /// Обработка входящего уведомления
  /** @param t - контекст вызова (ссылка на объект соединения )
    * @param req - запрос 
    */
  template<typename T>
  void notify(T& t, const hitlist_request& req )
  {
    std::vector<hit_item> res;
    if (req.type == hitlist_request::hits_m)
      hitlist->month_hitlist(req.first_id, req.offset, req.limit, res );
    else if (req.type == hitlist_request::hits_d)
      hitlist->day_hitlist(req.first_id, req.offset, req.limit, res );
    /// Отправляем уведомление в ответ
    t.get_aspect().template get<_hitlist_>().notify(t, res);
  }
};

typedef aa::tag_list_n<
  aa::tag<_hitlist_>,
  aa::gtag< ajr::_gmethod_ >
>::type hitlist_method_tag_list;

typedef aa::advice<
      hitlist_method_tag_list,
      ajr::method<hitlist_method>
    >
hitlist_method_advice;


#endif
